#include "ktableview.h"
#include <QStyledItemDelegate>
#include <QPainter>
#include <QHeaderView>
#include <QCheckBox>
#include <QApplication>
#include <QDebug>
#include <QMouseEvent>
#include <QToolButton>
#include <QItemSelectionModel>
#include "ktableheaderview.h"
#include "themeController.h"

namespace kdk {

class Q_DECL_HIDDEN TableDelegate :public QStyledItemDelegate
{
    Q_OBJECT
public:
    TableDelegate(QObject* parent);

    void updateState(Qt::CheckState state,const QModelIndex &index);

    QList<int> selectList();

protected:
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;

    virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;

Q_SIGNALS:
    void checkChange(int state);

public slots:
    void checkChangeSlot(int state);
    void onHoverIndexChanged(QModelIndex index);
//    void selectChange(int row);

private:
    QList<int> m_checkList;
    int m_hoverRow;
};

class Q_DECL_HIDDEN KTableViewPrivate : public QObject,public ThemeController
{
    Q_OBJECT
    Q_DECLARE_PUBLIC(KTableView)
public:
    KTableViewPrivate(KTableView *parent);
    virtual ~KTableViewPrivate();

    void changeTheme();


private:
    KTableView* q_ptr;
    KTableHeaderView* m_pHeaderView;
    TableDelegate* m_pDelegate;
};

KTableView::KTableView(QWidget *parent)
    :QTableView(parent)
    ,d_ptr(new KTableViewPrivate(this))
{
    Q_D(KTableView);
    setShowGrid(false);
    verticalHeader()->setVisible(false);
    setEditTriggers (QAbstractItemView::NoEditTriggers);
    setSelectionBehavior(QAbstractItemView::SelectRows);
    setMouseTracking(true);
    installEventFilter(this);

    d->m_pHeaderView = new KTableHeaderView(Qt::Horizontal,this);
    d->m_pHeaderView->installEventFilter(this);

    d->m_pDelegate = new TableDelegate(this);
    setItemDelegate(d->m_pDelegate);

    connect(d->m_pDelegate,&TableDelegate::checkChange,d->m_pHeaderView,[=](int state){
        d->m_pHeaderView->checkStateChangeSlot(state);
    });
    connect(d->m_pHeaderView,&KTableHeaderView::checkStateChange,d->m_pDelegate,[=](int state){
        d->m_pDelegate->checkChangeSlot(state);
        QItemSelectionModel *SelectionModel = selectionModel();
        if (SelectionModel)
        {
            SelectionModel->clearSelection();
        }
        emit hoverIndexChanged(QModelIndex());
    });

    connect(this,SIGNAL(hoverIndexChanged(QModelIndex)),d->m_pDelegate,SLOT(onHoverIndexChanged(QModelIndex)));
    connect(d->m_gsetting,&QGSettings::changed,this,[=]{
        d->changeTheme();
    });
}

void KTableView::setHorizontalTitle(QStringList list)
{
    Q_D(KTableView);
    d->m_pHeaderView->setTitle(list);
    setHorizontalHeader(d->m_pHeaderView);
}

KTableHeaderView *KTableView::headerView()
{
    Q_D(KTableView);
    if(d->m_pHeaderView)
        return d->m_pHeaderView;
}

QList<int> KTableView::selectList()
{
    Q_D(KTableView);
    return d->m_pDelegate->selectList();
}

void KTableView::mouseMoveEvent(QMouseEvent *event)
{
    QModelIndex index = indexAt(event->pos());
    emit hoverIndexChanged(index);
    QTableView::mouseMoveEvent(event);
    this->viewport()->update();
}

bool KTableView::eventFilter(QObject *object, QEvent *event)
{
    Q_D(KTableView);
    if(object == this)
    {
        switch (event->type()) {
        case QEvent::Leave:
            emit hoverIndexChanged(QModelIndex());
            break;
        default:
            break;
        }
    }
    if(object == d->m_pHeaderView)
    {
        switch (event->type()) {
        case QEvent::Enter:
            emit hoverIndexChanged(QModelIndex());
            break;
        default:
            break;
        }
    }
    this->viewport()->update();
    return QTableView::eventFilter(object,event);
}

KTableViewPrivate::KTableViewPrivate(KTableView *parent)
    :q_ptr(parent)
{

}

KTableViewPrivate::~KTableViewPrivate()
{

}

void KTableViewPrivate::changeTheme()
{
    initThemeStyle();
}

TableDelegate::TableDelegate(QObject *parent)
    :QStyledItemDelegate(parent)
{
    m_hoverRow = -1;
}

void TableDelegate::updateState(Qt::CheckState state, const QModelIndex &index)
{
    if(state == Qt::Checked)
    {
        m_checkList.append(index.row());
    }
    else if(state == Qt::Unchecked)
    {

        m_checkList.removeOne(index.row());
    }
    QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent());
    int count = view->model()->rowCount();

    if(m_checkList.count() == 0)
        emit checkChange(Qt::Unchecked);
    else if(m_checkList.count() == count)
        emit checkChange(Qt::Checked);
    else
        emit checkChange(Qt::PartiallyChecked);
}

void TableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QPalette pale;
    QColor bkgColor;
    QColor hoverColor;

    if(ThemeController::themeMode() == LightTheme)
    {
        if (index.row() % 2 == 0)
            bkgColor = QColor(245,245,245);
        else
            bkgColor = QColor(255,255,255);
        hoverColor = QColor(0,0,0);
        hoverColor.setAlphaF(0.05);
    }
    else
    {
        if (index.row() % 2 == 0)
            bkgColor = QColor(38,38,38);
        else
            bkgColor = QColor(18,18,18);
        hoverColor = QColor(255,255,255);
        hoverColor.setAlphaF(0.10);
    }
    if(index.row() == m_hoverRow && !option.state.testFlag(QStyle::State_Selected))
    {
        painter->fillRect(option.rect, hoverColor);
    }
    else
    {
        if(option.state.testFlag(QStyle::State_Selected))
            painter->fillRect(option.rect,pale.highlight().color());
        else
        {
            painter->fillRect(option.rect,bkgColor);
        }
        painter->setPen(Qt::NoPen);
        painter->drawRect(option.rect);
    }

    painter->setPen(pale.windowText().color());
    if(index.column() == 0)
    {
        QRect rect = option.rect;
        // 绘制复选框
        QStyleOptionButton checkBoxStyle;
        checkBoxStyle.rect = QRect(rect.x() + 8, rect.y() + (rect.height() - 16)/2, 16, 16);

        Qt::CheckState checkState = static_cast<Qt::CheckState>(index.data(Qt::CheckStateRole).toInt());
        checkBoxStyle.state = (checkState == Qt::Checked) ? QStyle::State_On : QStyle::State_Off;
        checkBoxStyle.state |= QStyle::State_Enabled;

        QApplication::style()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &checkBoxStyle, painter, option.widget);

        painter->drawText(option.rect.adjusted(checkBoxStyle.rect.right()+10,0,0,0), index.data(Qt::DisplayRole).toString());
    }
    else
    {
        painter->drawText(option.rect, index.data(Qt::DisplayRole).toString());
    }

}

bool TableDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    if((event->type() == QEvent::MouseButtonRelease) && (index.column() == 0))
    {
        QMouseEvent *mouse_event = static_cast<QMouseEvent*>(event);
       if(mouse_event->button() == Qt::LeftButton)
        {
            QRect r(option.rect.left()+8,option.rect.y() + (option.rect.height() - 16)/2,16,16);
            bool flag = r.contains(mouse_event->pos());
            if(flag)
            {
                //根据当前单元格的选中状态来在 选中/未选中 之间切换
                QVariant value = index.data(Qt::CheckStateRole);
                Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
                                        ? Qt::Unchecked : Qt::Checked);

                //设置当前单元格的选中状态
                bool checkState=model->setData(index,state, Qt::CheckStateRole);
                updateState(state,index);
                return checkState;
            }
        }
        return false;
    }
    else
        return QStyledItemDelegate::editorEvent(event,model,option,index);
}

QList<int> TableDelegate::selectList()
{
    return m_checkList;
}

void TableDelegate::checkChangeSlot(int state)
{
    m_checkList.clear();
    QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent());
    int count = view->model()->rowCount();
    Qt::CheckState checkState;

    for(int i=0 ; i <count ;i++ )
    {
        if(state == 0)
        {
            m_checkList.append(view->model()->index(i,0).row());
            checkState = Qt::Unchecked;
        }
        else
        {
            m_checkList.removeOne(view->model()->index(i,0).row());
            checkState = Qt::Checked;
        }
        //设置当前单元格的选中状态
        view->model()->setData(view->model()->index(i,0),checkState, Qt::CheckStateRole);
        updateState(checkState,view->model()->index(i,0));
    }
}

void TableDelegate::onHoverIndexChanged(QModelIndex index)
{
    if(index.isValid())
    {
        m_hoverRow = index.row();
    }
    else
    {
        m_hoverRow = -1;
    }
}

}

#include "ktableview.moc"
#include "moc_ktableview.cpp"
